package modellayer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * Subclasses of this abstract class can easily <code>save()</code> and <code>load()</code>
 * an object that implements the <code>Serializable</code> interface. Typical
 * use is a container subclass that wants to turn some volatile
 * memory (an object) into non-volatile memory (into a file)
 * and visa-versa.
 * <p>
 * Only the subclass is aware of the object-type after a <code>load()</code>.
 * Thus the subclass must override the abstract method and cast
 * the <code>loaded</code>-parameter to this same object-type like this:
 * 	
 * <blockquote><pre><code>
 * protected void updateFileItObject(Object loaded)
 * {
 *   someObject = (SomeObjectType) loaded;
 * }
 * </code></pre></blockquote>
 * 
 * Also to make this abstract superclass aware of the object to
 * <code>save()</code> and <code>load()</code>, and aware of which file to use, this
 * constructor skeleton can be used in the subclass:
 * 
 * <blockquote><pre><code>
 * public SomeSubclassConstructor(String fileName)
 * {
 *   super(fileName);
 *   someObject = new SomeObjectType();
 *   super.setFileItObject(someObject);
 * }
 * </code></pre></blockquote>
 * 
 * Now the methods <code>save()</code> and <code>load()</code> will save and load "someObject"
 * automatically to and from the specified file.
 *  
 * @author (ucn-1semprojekt-dm78-gruppe1)
 *
 */
public abstract class FileIt
{
	private ObjectOutputStream oout;
	private ObjectInputStream oin;
	
	private String fileName;
	private Object fileItObject;
	
	/**
	 * @param fileName the file used to save and load the object
	 */
	public FileIt(String fileName)
	{
		this.fileName = fileName;
	}
	
	
	/**
	 * Set the object to file
	 * @param fileItOject the object to save and load to and from file
	 */
	protected void setFileItObject(Object fileItObject)
	{
		this.fileItObject = fileItObject;
	}
	
	/**
	 * Saves the object. A new file will be created,
	 * if a file does not exist.
	 */
	public void save()
	{
		try
		{
		FileOutputStream stream = new FileOutputStream(fileName);
		oout = new ObjectOutputStream(stream);
		oout.writeObject(fileItObject);
		}
		catch (IOException msg) {}
		finally 
		{ 
			try
			{
				if (oout != null) oout.close();
			}
			catch (IOException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
	}
	

	/**
	 * Load's the object and calls the abstract method
	 * <code>updateFileItObject(Object loaded)</code> implemented 
	 * by the subclass.
	 */
	public void load()
	{
		Object loaded = null;
		try
		{
			FileInputStream stream = new FileInputStream(fileName);
			oin = new ObjectInputStream(stream);
			loaded = oin.readObject();
		}
		catch (IOException msg) {}
		catch (ClassNotFoundException msg) {}
		finally
		{
			try
			{
				if (oin != null) oin.close();
			}
			catch (IOException msg) {}
		}
		if (loaded != null) this.fileItObject = loaded;
		updateFileItObject(this.fileItObject);
	}

	/**
	 * Only the subclass implementing this method is aware
	 * of the correct object-type to cast.
	 * @param loaded must be cast to the correct object-type
	 */
	protected abstract void updateFileItObject(Object loaded);
	
	
}
